iT邦幫忙

第 12 屆 iThome 鐵人賽

DAY 22
0
自我挑戰組

滿滿的紅寶石不拿嗎?-- 去吧!我把世界上的一切都放在那裡了! 系列 第 22

attr_accessor <> 喲嚯嚯嚯~可以讓我看一下你的 code 嗎? - 滿滿的紅寶石不拿嗎?

  • 分享至 

  • xImage
  •  

[Day22] 靈魂之王布魯克為您表演~45度角!

學寫程式也有一陣子了,但直到最近才發現很多時候自己都只是知其然而不知其所以然,而沒有完全了解自己在寫的到底是什麼。

所以這篇就要來提一些很常被用到,但還不是非常清楚的東西:

什麼是 getter

顧名思義,就是「取得(某個東西)」的方法,在 Ruby 裡,我們會把取出實體變數這件事稱為 getter ,指的就是取出實體變數的方法。

class Cat
  def initialize(name)
    @name = name
  end
end

miru = Cat.new('miru')

miru.name
=> NoMethodError (undefined method `name' for #<Cat:0x00007ff82783a578 @name="miru">)

在類別裡,沒有 getter 就無法取出實體變數的值。所以 miru 這個實體拿不到類別裡的實體變數 @name,如果要拿到 @name 的話,就必須給它一個 getter

class Cat
  def initialize(name)
    @name = name
  end

  def name    #getter method
    @name
  end
end

miru = Cat.new('miru')
miru.name
=> "miru"

然而,如果每次要取實體變數的值都要重寫一次 getter ,嗯...用想的都覺得麻煩啊!因此超好用的 attr三兄弟 就誕生了!(登愣!)

指令 說明
attr_reader 用來取出實體變數。
attr_writer 用來指派實體變數。
attr_accessor 結合以上兩者,可取出也可指派實體變數。

讚嘆工程師們懶惰的美德!


attr_reader

attr_reader 可以幫助我們取出實體變數。

class Cat
  attr_reader :name
  
  def initialize(name)
    @name = name
  end
end

miru = Cat.new('miru')
miru.name
=> "miru"

跟剛剛完全一樣!改成用 attr_reader :name ,所以不用再寫:

def name
  @name
end

一行抵三行,超級划算!


什麼是 setter

setter 也很好理解,就是「指派」的意思,在 Ruby 裡,我們會定義一個 setter 方法,透過呼叫這個方法,就可以重新指派實體變數。

attr_writer

我們延續剛剛的例子,如果今天有一隻叫做 miru 的貓

class Cat
  attr_reader :name
  
  def initialize(name)
    @name = name
  end
end

miru = Cat.new('miru')
miru.name
=> "miru"

而我想替祂換個更響亮的名字,結果不管怎麼寫通通都失敗了!

miru.name"neko"
=> ArgumentError (wrong number of arguments (given 1, expected 0))

miru.name."neko"
=> SyntaxError ((irb):14: syntax error, unexpected tSTRING_BEG)

miru.name = "neko"
=> NoMethodError (undefined method `name=' for #<Cat:0x00007fada005f780 @name="miru">

這是因為,在這個類別裡並沒有 setter ,因此產出的實體變數無法重新指派一個新的值。

那我們試試看加上 setter

class Cat
  attr_reader :name
  
  def initialize(name)
    @name = name
  end
  
  def name=(name)
    @name = name
  end
end

miru = Cat.new('miru')
miru.name
=> "miru"

這時候就可以幫 miru 換個更好聽的名字了!

miru.name=("neko")
=> "neko" 
miru.name
=> "neko"

而由於 Ruby 可以省略小括號的特性,以下這兩種 setter 的寫法可能更常見:

def name= name
  @name = name
end
def name = name
  @name = name
end

在使用上也可以:

miru.name = "puma"
=> "puma" 

也因為這樣,才會説實體變數也是實體物件的屬性(attribute),這其中大部分的原因就是 setter 造成的!

當然,更懶惰的寫法就是用 attr_writer 啦!

class Cat
  attr_reader :name
  attr_writer :name
  
  def initialize(name)
    @name = name
  end
end

miru = Cat.new('miru')
miru.name
=> "miru"

同樣也是一行抵三行啦!


attr_accessor

然而,沒有最懶,只有更懶。

attr_accessor 就是整合了前面兩者效果的神奇好夥伴,用了 attr_accessor 以後程式碼都變得超乾淨!等於一次擁有 attr_readerattr_writer

class Cat
  attr_accessor :name
  
  def initialize(name)
    @name = name
  end
end

miru = Cat.new('miru')
miru.name
=> "miru"
miru.name = "wolf"
miru.name
=> "wolf"

是不是很心動!趕快打開 irb 玩玩看吧!

關於 attr_accessor ,大家可以拜讀龍哥這篇 Ruby 語法放大鏡之「attr_accessor 是幹嘛的?」,裡面有更多更專業的說明!


今天就介紹到這邊啦!大家明天見!


上一篇
實體變數 <> 一流強者都要會的武裝色霸氣 - 滿滿的紅寶石不拿嗎?
下一篇
empty? nil? blank? <> 聽說今天是滿月?戰鬥力爆表的月亮獅子變身!- 滿滿的紅寶石不拿嗎?
系列文
滿滿的紅寶石不拿嗎?-- 去吧!我把世界上的一切都放在那裡了! 30
圖片
  直播研討會
圖片
{{ item.channelVendor }} {{ item.webinarstarted }} |
{{ formatDate(item.duration) }}
直播中

尚未有邦友留言

立即登入留言